package com.ruoyi.foo;

import com.ruoyi.common.constant.HttpStatus;
import io.restassured.http.ContentType;
import io.restassured.module.mockmvc.response.ValidatableMockMvcResponse;
import org.apache.commons.lang3.NotImplementedException;
import org.hamcrest.Matcher;
import org.springframework.util.Assert;
import org.springframework.web.util.UriComponentsBuilder;

import static io.restassured.module.mockmvc.RestAssuredMockMvc.given;
import static org.hamcrest.Matchers.*;

/**
 * Mock http request
 */
public class MockRequest {
    private ValidatableMockMvcResponse validatableMockMvcResponse;
    private final String basePath;
    private String url;

    public MockRequest(String basePath) {
        this.basePath = basePath;
        this.url = basePath;
    }

    public void appendUrl(String path, Object... pathParams) {
        Assert.isTrue(path.startsWith("/"), "路径必须以/开头");
        this.url = UriComponentsBuilder.fromUriString(this.basePath + path).buildAndExpand(pathParams).encode().toUriString();
    }

    public MockRequest get() {
        validatableMockMvcResponse =
                given()
                    .contentType(ContentType.JSON)
                .when()
                    .get(url)
                .then()
                    .statusCode(HttpStatus.SUCCESS)
                    .assertThat();
        return this;
    }

    public MockRequest get(Object queryParams) {
        throw new NotImplementedException("TODO");
    }

    public MockRequest post(Object body) {
        validatableMockMvcResponse =
                given()
                    .contentType(ContentType.JSON)
                    .body(body)
                .when()
                    .post(url)
                .then()
                    .statusCode(HttpStatus.SUCCESS)
                    .assertThat();
        return this;
    }

    public MockRequest put(Object body) {
        validatableMockMvcResponse =
                given()
                    .contentType(ContentType.JSON)
                    .body(body)
                .when()
                    .put(url)
                .then()
                    .statusCode(HttpStatus.SUCCESS)
                    .assertThat();
        return this;
    }

    public MockRequest delete() {
        validatableMockMvcResponse =
                given()
                    .contentType(ContentType.JSON)
                .when()
                    .delete(url)
                .then()
                    .statusCode(HttpStatus.SUCCESS)
                    .assertThat();
        return this;
    }

    public MockRequest delete(Object body) {
        validatableMockMvcResponse =
                given()
                    .contentType(ContentType.JSON)
                    .body(body)
                .when()
                    .delete(url)
                .then()
                    .statusCode(HttpStatus.SUCCESS)
                    .assertThat();
        return this;
    }

    public MockRequest isCodeEqualTo(int value) {
        return should("code", equalTo(value));
    }

    public MockRequest isMsgEqualTo(String value) {
        return should("msg", equalTo(value));
    }

    public MockRequest isDataNullValue() {
        return should("data", nullValue());
    }

    public MockRequest isDataNotNullValue() {
        return should("data", notNullValue());
    }

    public MockRequest isNullValue(String key) {
        return should(key, nullValue());
    }

    public MockRequest hasRowsSize(int size) {
        return should("rows.size()", equalTo(size));
    }

    public MockRequest isTotalEqualTo(int value) {
        return should("total", equalTo(value));
    }

    public MockRequest hasDataSize(int size) {
        return should("data.size()", equalTo(size));
    }

    private MockRequest should(String path, Matcher<?> matcher) {
        Assert.notNull(validatableMockMvcResponse, "请先调用 get/post/put/delete 方法发起 http 请求");
        validatableMockMvcResponse.body(path, matcher);
        return this;
    }
}
